<template>
  <div :id="galleryID" class="gallery-container"
       :style="{ width: `${psw}px`, height: `${psh}px` }">
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, watch, toRefs } from 'vue'

import { loadImageDimensions } from './utils/assetsSize'
import openPhotoSwipe from './utils/videoPlugin'
import Timer from './utils/timer'

const props = defineProps({
  galleryID: { type: String, required: true },
  images: { type: Array, required: true },  // 指定的图像数据,
  psw: { type: Number, required: true },  // 指定的宽度
  psh: { type: Number, required: true }, // 指定的高度
  autoplay: { type: Boolean, default: true, required: false }, // 是否自动播放视频
  startIndex: { type: Number, default: 0, required:false }, // 初始展示的索引
  bgOpacity: { type: Number, default: 0.5, required:false }, // 背景不透明度
  showArrow: { type: Boolean, default: true, required:false }, // 是否展示左右箭头
  showNavigation: { type: Boolean, default: false, required:false }, // 是否展示navigation
  navigationStyle: { type: Object, required:false,
    default:() => ({ size: 20, color: '#fff', activeColor: '#008000', spacing: 5 })
  }, // navigation样式
  useChanged: { type: Boolean, default: false, required:false }, // 是否使用changed事件(回调当前资源索引)
})

const $emit = defineEmits(['changed'])
const assetsID = ref(-1)
let timer = new Timer(1000,5)
const imagesData = ref(props.images)
const { galleryID, psw, psh, autoplay, startIndex, bgOpacity, showNavigation } = toRefs(props)
let photoswipe = null
const bullets = []

// 监听 props.images 的变化，确保图片数据更新时 PhotoSwipe 也更新
// watch(() => props.images, (newImages) => {
//   imagesData.value = newImages
//   initDimensions()
// })
watch(assetsID, (newValue, oldValue) => {
  // console.log('assetsID------->',newValue)
  if(props.useChanged)$emit('changed', newValue)

  timer.stop()
  const element = photoswipe.currSlide.content.element
  if(autoplay.value){
    if(!isVideo()) {
      imageTiming()
    }
  }else{
    if(isVideo()) {
      element.pause()
    }
  }

  if(bullets.length > 0){
    for(let i = 0; i<bullets.length; i++) {
      bullets[i].classList.remove('pswp__bullet--active')
      bullets[i].style.background = props.navigationStyle.color
    }
    bullets[newValue].classList.add('pswp__bullet--active')
    bullets[newValue].style.background = props.navigationStyle.activeColor
  }
})

const initDimensions = async () => {
  for (const item of imagesData.value) {
    if (item.type === 'image') {
      await handleImage(item)
    }else if (isVideo()) {
      item.width = psw.value
      item.height = psh.value
    }
  }
  const viewportSize = { width: psw.value, height: psh.value }
  photoswipe = openPhotoSwipe(imagesData.value,{
    index:startIndex.value,
    closeOnVerticalDrag: false, // 垂直拖动手势关闭
    pinchToClose: false, // 捏合触摸手势可关闭
    arrowPrev: props.showArrow,
    arrowNext: props.showArrow,
    bgOpacity: bgOpacity.value,
    zoom: false,
    close: false,
    counter: false,
    bgClickAction:(releasePoint, e) => {},
    appendToEl: document.querySelector(`#${galleryID.value}`),
    getViewportSizeFn: function(options, pswp) {
      return {
        x: viewportSize.width,
        y: viewportSize.height
      }
    }
  })
  photoswipe.eventEmitter.on('contentActivate', slideActivate)
  photoswipe.eventEmitter.on('videoEnded', videoAssetsEnded)
  photoswipe.on('pointerDown',pointerDown)
  photoswipe.on('pointerUp',pointerUp)

  if(showNavigation.value){
    const { size, color, spacing } = props.navigationStyle
    photoswipe.ui.registerElement({
      name: 'bulletsIndicator',
      className: 'pswp__bullets-indicator',
      appendTo: 'wrapper',
      onInit:(el, pswp) => {
        let bullet;

        for (let i = 0; i < pswp.getNumItems(); i++) {
          bullet = document.createElement('div')
          bullet.className = 'pswp__bullet'
          bullet.style.width =  `${size}px`
          bullet.style.height =  `${size}px`
          bullet.style.background =  color
          bullet.style.margin =  `0 ${spacing}px`
          bullet.onclick = (e) => {
            pswp.goTo(bullets.indexOf(e.target))
          }
          el.appendChild(bullet)
          bullets.push(bullet)
        }
      }
    })
  }
}

const imageTiming = () => {
  timer.updateRepeatCount(imagesData.value[assetsID.value].duration)
  timer.reset()
  timer.start()
}

const slideActivate = (event) => {
  const content = event.detail;
  assetsID.value = content.content.index
}

const videoAssetsEnded = (event) => {
  // console.log('收到视频播放结束事件：', event)
  if(autoplay.value && photoswipe)photoswipe.next()
}

const pointerDown = () => {
  // console.log('PointerDown')
  timer.stop()
}
const pointerUp = () => {
  // console.log('PointerUp')
  if(autoplay.value && !isVideo()){
    timer.reset()
    timer.start()
  }
}

const handleImage = async (item) => {
  const { width, height } = await loadImageDimensions(item)
  item.width = width
  item.height = height
}

const isVideo = () => imagesData.value[assetsID.value]?.type === 'video'

const gotoSlide = (index) => {
  if(photoswipe)photoswipe.goTo(index)
}

const manageSlide = (isPlay = true) => {
  if(photoswipe){
    const element = photoswipe.currSlide.content.element
    if(isPlay){
      if(isVideo()){
        element.play()
      }else{
        if(autoplay.value){
          timer.reset()
          timer.start()
        }
      }
    }else{
      if(isVideo()){
        element.pause()
      }else{
        timer.stop()
      }
    }
  }
}

const onTimer = (index) => {
  if(photoswipe)photoswipe.next()
}

onMounted(() => {
  initDimensions()
  timer.addEventListener('complete', onTimer)
})

onUnmounted(() => {
  // 清理 PhotoSwipe 实例
  if (photoswipe) {
    if(photoswipe.eventEmitter){
      photoswipe.eventEmitter.off('contentActivate', slideActivate)
      photoswipe.eventEmitter.off('videoEnded', videoAssetsEnded)
      photoswipe.eventEmitter = null
    }
    photoswipe.off('pointerDown', pointerDown)
    photoswipe.off('pointerUp', pointerUp)
    photoswipe.close()
    photoswipe = null
  }
  timer.stop()
  timer.removeEventListener('complete', onTimer)
  timer = null

  if(bullets.length > 0){
    for (let i = 0; i < bullets.length; i++) {
      let bullet = bullets[i]
      bullet.parentNode.removeChild(bullet)
      bullet = null
    }
    bullets.length = 0
  }
})

defineExpose({
  assetsID,
  gotoSlide,
  manageSlide
})
</script>

<style scoped>
.gallery-container{
  background-color: transparent;
  position: relative;
}
:deep .pswp{
  position: absolute !important;
}
:deep .pswp__bullets-indicator {
  display: flex;
  flex-direction: row;
  align-items: center;

  position: absolute;
  bottom: 30px;
  left: 50%;
  transform: translate(-50%, 0);
}
:deep .pswp__bullet {
  border-radius: 50%;
}
:deep .pswp__bullet--active {
  background: green;
}
</style>